home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / program / wil4c10.zip / MAIL.C < prev    next >
C/C++ Source or Header  |  1997-07-26  |  29KB  |  886 lines

  1. /*
  2. **  MAIL.C
  3. **
  4. **  POP3/SMTP client, uses ASYNC functions.
  5. **
  6. **  This program can:
  7. **
  8. **  (1) Check status of POP3 account.
  9. **  (2) Mail a file.
  10. **  (3) Get mail.
  11. **  (4) Delete mail.
  12. **
  13. **  Note that this program reads MAIL.INI.
  14. */
  15.  
  16. #include <windows.h>
  17. #include <winsock.h>
  18.  
  19. #include "wil.h"
  20. #include "about.h"
  21. #include "async.h"
  22. #include "message.h"
  23. #include "paint.h"
  24. #include "readini.h"
  25. #include "str.h"
  26. #include "unique.h"
  27.  
  28. #ifdef WIN32
  29. #define USE_INS HINSTANCE
  30. #define USE_PTR PSTR
  31. #else
  32. #define USE_INS HANDLE
  33. #define USE_PTR LPSTR
  34. #endif
  35.  
  36. LRESULT CALLBACK MainWndProc(HWND, UINT, WPARAM, LPARAM);
  37.  
  38. /* globals */
  39.  
  40. HWND hMainWnd;            /* main window handle */
  41.  
  42. #define BS            8
  43. #define LF           10
  44. #define CR           13
  45. #define ESC          27
  46.  
  47. #define MAX_BUF     512
  48. #define STR_SIZE     50
  49.  
  50. #define POP3_PORT   110
  51. #define SMTP_PORT    25
  52.  
  53. #define MAIL_CMD_FAILURE      100
  54. #define POP3_COMMAND          101
  55. #define POP3_CONN_SUCCESS     102
  56. #define POP3_USER_SUCCESS     103
  57.  
  58. #define POP3_QUIT_BEGIN       201
  59. #define POP3_QUIT_SUCCESS     202
  60. #define POP3_QUIT_FAILURE     203
  61.  
  62. #define MAIL_CHK_BEGIN        301
  63. #define MAIL_CHK_MSG_COUNT    302
  64. #define MAIL_CHK_NEXT_HEADER  303
  65. #define MAIL_CHK_TOP_SUCCESS  304
  66. #define MAIL_CHK_READ_SUCCESS 305
  67.  
  68. #define MAIL_DEL_BEGIN        401
  69.  
  70. #define MAIL_GET_BEGIN        501
  71. #define MAIL_GET_READ         502
  72.  
  73. #define MAIL_PUT_BEGIN        601
  74. #define MAIL_PUT_CONN_SUCCESS 602
  75. #define MAIL_PUT_HELO_SUCCESS 603
  76. #define MAIL_PUT_FROM_SUCCESS 604
  77. #define MAIL_PUT_TO_SUCCESS   605
  78. #define MAIL_PUT_DATA_SUCCESS 606
  79. #define MAIL_PUT_SEND         607
  80.  
  81. #define SMTP_QUIT_BEGIN       701
  82. #define SMTP_QUIT_SUCCESS     702
  83. #define SMTP_QUIT_FAILURE     703
  84.  
  85. static USE_INS hInstance;
  86. static int WinWidth = 8 * NCOLS;  /* window width */
  87. static int WinHeight = 15 * NROWS;/* window height */
  88. static char Temp[MAX_BUF+8];      /* temprary buffer */
  89. static int  InBufCmd = 0;         /* command */
  90. static int  InBufLen = 0;         /* length of string in InBuffer[] */
  91. static char InBuffer[MAX_BUF+1];  /* input buffer */
  92. static SOCKET Socket = 0;         /* socket */
  93. static int MailID;                /* mail message number */
  94. static int EchoFlag = 0;          /* echo commands of TRUE */
  95. static int PassFlag = 0;          /* replace echoed chars with '*' if TRUE */
  96. static HCURSOR ArrowCursor;       /* arrow cursor */
  97. static HCURSOR WaitCursor;        /* hour glass cursor */
  98. static LPSTR BufferPtr;           /* pointer to buffer in ASYNC */
  99. static int MsgCount;
  100. static int MsgIndex;
  101. static int POP3SuccessMsg;        /* message on success of POP3 command */
  102. static int POP3FailureMsg;        /* message on failure of POP3 command */
  103.  
  104. static char SmtpString[STR_SIZE] = "";  /* SMTP server */
  105. static char Pop3String[STR_SIZE] = "";  /* POP3 server */
  106. static char UserString[STR_SIZE] = "";  /* POP3 user */
  107. static char PassString[STR_SIZE] = "";  /* POP3 password */
  108. static char FromString[STR_SIZE] = "";  /* our email address */
  109. static char MailFile[STR_SIZE] = "";    /* name of file to mail */
  110. static char ToString[STR_SIZE] = "";    /* destination (user@adress) */
  111.  
  112. /* disable menu item list */
  113.  
  114. static void DisableMenuItems(int First, int Last)
  115. {int i;
  116.  HMENU hMenu;
  117.  hMenu = GetMenu(hMainWnd);
  118.  for(i=First;i<=Last;i++)
  119.     EnableMenuItem(hMenu,i,MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
  120.  DrawMenuBar(hMainWnd);
  121. }
  122.  
  123. /* enable menu item list */
  124.  
  125. static void EnableMenuItems(int First, int Last)
  126. {int i;
  127.  HMENU hMenu;
  128.  hMenu = GetMenu(hMainWnd);
  129.  for(i=First;i<=Last;i++)
  130.     EnableMenuItem(hMenu,i,MF_BYCOMMAND | MF_ENABLED);
  131.  DrawMenuBar(hMainWnd);
  132. }
  133.  
  134. /* disable POP/SMTP menu items */
  135.  
  136. static void DisableMailMenuItems(void)
  137. {
  138.  DisableMenuItems(MSG_MAIL_CHK, MSG_MAIL_DEL);
  139. }
  140.  
  141. /* enable POP/SMTP menu items */
  142.  
  143. static void EnableMailMenuItems(void)
  144. {
  145.  EnableMenuItems(MSG_MAIL_CHK, MSG_MAIL_DEL);
  146. }
  147.  
  148. /* add character to input buffer */
  149.  
  150. static void Add2Buffer(char Chr)
  151. {int i;
  152.  /* add char to input buffer */
  153.  switch(Chr)
  154.    {case BS:
  155.       if(InBufLen>0)
  156.         {/* backup on screen */
  157.          DisplayChar(BS);
  158.          /* remove last char from buffer */
  159.          InBufLen--;
  160.         }
  161.       break;
  162.     case ESC:
  163.       for(i=1;i<=InBufLen;i++) DisplayChar(BS);
  164.       InBufLen = 0;
  165.       DestroyCaret();
  166.       break;
  167.     default:
  168.       /* display char */
  169.       if(PassFlag) DisplayChar('*');
  170.       else DisplayChar(Chr);
  171.       /* put into buffer */
  172.       if(InBufLen<MAX_BUF) InBuffer[InBufLen++] = Chr;
  173.       break;
  174.    }
  175. }
  176.  
  177. /* place the cursor in the display window */
  178.  
  179. static void SetTheFocus(void)
  180. {/* create client area caret */
  181.  CreateCaret(hMainWnd,NULL,3,10);
  182.  SetCaretPos(PaintGetColPos(),PaintGetRowPos());
  183.  ShowCaret(hMainWnd);
  184. }
  185.  
  186. /* display error message */
  187.  
  188. static void DisplayError(int Code, LPSTR Msg)
  189. {wsprintf((LPSTR)Temp,"ERROR %d: ",Code);
  190.  DisplayString((LPSTR)Temp);
  191.  if(Msg) DisplayString(Msg);
  192.  if(Code)
  193.    {wilErrorText(Code,(LPSTR)Temp,50);
  194.     DisplayLine((LPSTR)Temp);
  195.    }
  196.  /* restore arrow cursor */
  197.  SetCursor(ArrowCursor);
  198. }
  199.  
  200. /* start POP3 command sequence */
  201.  
  202. void Pop3Command(int OnSuccess, int OnFailure)
  203. {POP3SuccessMsg = OnSuccess;
  204.  POP3FailureMsg = OnFailure;
  205.  POST_MSG(POP3_COMMAND);
  206. }
  207.  
  208. /* read text line (ending with LF) from disk */
  209.  
  210. static int ReadTextLine(int Handle, LPSTR Buffer, int BufLen)
  211. {char Ch;
  212.  int  i;
  213.  int  Size = 0;
  214.  static char TextBuffer[128];
  215.  static int  TextLeft = 0;
  216.  static int  TextRight = 0;
  217.  while(1)
  218.    {/* is TextBuffer[] empty ? */
  219.     if(TextLeft>=TextRight)
  220.       {/* read from disk */
  221.        TextLeft = 0;
  222.        TextRight = _lread(Handle,(LPSTR)TextBuffer,125) - 1;
  223.        if(TextRight<0) return -1;
  224.       }
  225.     /* copy till LF or end of buffer */
  226.     for(i=TextLeft;i<=TextRight;i++)
  227.       {Ch = TextBuffer[i];
  228.        Buffer[Size++] = 0x7f & Ch;
  229.        if(Ch=='\n')
  230.          {/* found LF */
  231.           Buffer[Size] = '\0';
  232.           TextLeft = i + 1;
  233.           return Size;
  234.          }
  235.        /* is Buffer[] filled ? */
  236.        if(Size==BufLen-3)
  237.          {/* end with CR/LF */
  238.           Buffer[Size++] = '\r';
  239.           Buffer[Size++] = '\n';
  240.           Buffer[Size] = '\0';
  241.           TextLeft = i + 1;
  242.           return Size;
  243.          }
  244.       }
  245.     /* used up all of TextBuffer[] */
  246.     TextLeft = TextRight;
  247.    } /* end-while */
  248. }
  249.  
  250. /* WinMain */
  251.  
  252. #ifdef WIN32
  253. int WINAPI
  254. #else
  255. int PASCAL
  256. #endif
  257. WinMain(USE_INS hInst, USE_INS hPrevInstance,
  258.         USE_PTR szCmdLine,  int nCmdShow)
  259. {WNDCLASS  wc;
  260.  MSG msg;
  261.  BOOL Result;
  262.  if(!hPrevInstance)
  263.    {/* register main window class */
  264.     wc.style = CS_HREDRAW | CS_VREDRAW;
  265.     wc.lpfnWndProc = MainWndProc;
  266.     wc.cbClsExtra = 0;
  267.     wc.cbWndExtra = 0;
  268.     wc.hInstance = hInst;
  269.     wc.hIcon = LoadIcon(hInst, "HostIcon");
  270.     wc.hCursor = NULL;
  271.     wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
  272.     wc.lpszMenuName =  "HostMenu";
  273.     wc.lpszClassName = "HostWClass";
  274.     Result = RegisterClass(&wc);
  275.     if(!Result) return FALSE;
  276.    }
  277.  
  278.  /* create main window */
  279.  hInstance = hInst;
  280.  hMainWnd = CreateWindow(
  281.         "HostWClass",   "Mail",    WS_OVERLAPPEDWINDOW,
  282.         CW_USEDEFAULT,  CW_USEDEFAULT,
  283.         WinWidth,       WinHeight,
  284.         NULL,           NULL,
  285.         hInstance,      NULL);
  286.  ShowWindow(hMainWnd, nCmdShow);
  287.  UpdateWindow(hMainWnd);
  288.  
  289.  /* window control loop */
  290.  
  291.  while(GetMessage(&msg,NULL,0,0))
  292.    {
  293.     TranslateMessage(&msg);
  294.     DispatchMessage(&msg);
  295.    }
  296.  return (msg.wParam);
  297. } /* end WinMain */
  298.  
  299. #ifdef WIN32
  300. LRESULT CALLBACK
  301. #else
  302. long FAR PASCAL
  303. #endif
  304. MainWndProc(HWND hWindow,UINT iMsg,WPARAM wParam,LPARAM lParam)
  305. {int Code;
  306.  HDC hDC;
  307.  PAINTSTRUCT ps;
  308.  int i, n;
  309.  char Chr;
  310.  LPSTR Ptr;
  311.  static int  BufSize;
  312.  static char LastChar;
  313.  static int  Handle = 0;
  314. #ifdef WIN32
  315. #else
  316.  static FARPROC lpfnAboutDlgProc;
  317. #endif
  318.  /* begin */
  319.  hMainWnd = hWindow;
  320.  switch (iMsg)
  321.     {case WM_CREATE:
  322.       /* create cursors */
  323.       ArrowCursor = LoadCursor(NULL, IDC_ARROW);
  324.       WaitCursor = LoadCursor(NULL, IDC_WAIT);
  325.       SetCursor(ArrowCursor);
  326. #ifdef WIN32
  327. #else
  328.        /* create thunk for Win16 */
  329.        lpfnAboutDlgProc = MakeProcInstance(AboutDlgProc,hInstance);
  330. #endif
  331.       /* initialize paint module */
  332.       PaintInit();
  333.       /* attach WINSOCK */
  334.       DisplayString("Attaching WINSOCK...");
  335.       Code = wilAttach();
  336.       DisplayLine("OK");
  337.       if(Code<0) DisplayError(Code,"wilAttach fails:");
  338.       else
  339.         {wsprintf((LPSTR)Temp," Description: %s", wilGetDescription() );
  340.          DisplayLine((LPSTR)Temp);
  341.          wsprintf((LPSTR)Temp," My HostName: %s", wilGetMyHostName() );
  342.          DisplayLine((LPSTR)Temp);
  343.          wsprintf((LPSTR)Temp," My HostAddr: %s", wilGetMyHostDotted(0) );
  344.          DisplayLine((LPSTR)Temp);
  345.         }
  346.       /* open MAIL.INI file */
  347.       if(!IniOpen("MAIL.INI"))
  348.         {DisableMailMenuItems();
  349.          break;
  350.         }
  351.       while(1)
  352.         {/* read next line from MAIL.INI */
  353.          if(IniRead((LPSTR)Temp)<0) break;
  354. #if 0
  355.          /* echo strings */
  356.          DisplayLine((LPSTR)Temp);
  357. #endif
  358.          /* test for all legal keywords */
  359.          IniExtract((LPSTR)Temp,"POP3",(LPSTR)Pop3String);
  360.          IniExtract((LPSTR)Temp,"USER",(LPSTR)UserString);
  361.          IniExtract((LPSTR)Temp,"PASS",(LPSTR)PassString);
  362.          IniExtract((LPSTR)Temp,"SMTP",(LPSTR)SmtpString);
  363.          IniExtract((LPSTR)Temp,"FROM",(LPSTR)FromString);
  364.         }
  365.       /* verify that we have all strings read in */
  366.       if(lstrlen((LPSTR)Pop3String)==0) DisplayLine("ERROR: Missing POP3 server name.");
  367.       if(lstrlen((LPSTR)UserString)==0) DisplayLine("ERROR: Missing POP3 user name.");
  368.       if(lstrlen((LPSTR)SmtpString)==0) DisplayLine("ERROR: Missing SMTP user name.");
  369.       if(lstrlen((LPSTR)FromString)==0) DisplayLine("ERROR: Missing POP3 'From' address.");
  370.       if(lstrlen((LPSTR)PassString)==0) DisplayLine("WARNING: Missing POP3 password.");
  371.       break;
  372.  
  373.      case WM_COMMAND:
  374.          switch(wParam)
  375.            {
  376.             case MSG_ABOUT :
  377. #ifdef WIN32
  378.                DialogBox(hInstance, "AboutBox", hMainWnd, AboutDlgProc);
  379. #else
  380.                DialogBox(hInstance, "AboutBox", hMainWnd, lpfnAboutDlgProc);
  381. #endif
  382.                return 0;
  383.  
  384.             case MSG_DEBUG:
  385.               wsprintf((LPSTR)Temp,"DEBUG: SmtpString=[%s]", (LPSTR)SmtpString);
  386.               DisplayLine((LPSTR)Temp);
  387.               wsprintf((LPSTR)Temp,"DEBUG: Pop3String=[%s]", (LPSTR)Pop3String);
  388.               DisplayLine((LPSTR)Temp);
  389.               wsprintf((LPSTR)Temp,"DEBUG: UserString=[%s]", (LPSTR)UserString);
  390.               DisplayLine((LPSTR)Temp);
  391.               wsprintf((LPSTR)Temp,"DEBUG: PassString=[%s]", (LPSTR)PassString);
  392.               DisplayLine((LPSTR)Temp);
  393.               break;
  394.  
  395.             case MSG_ECHO:
  396.               EchoFlag = 1 - EchoFlag;
  397.               DisplayString("Echo flag is now ");
  398.               if(EchoFlag) DisplayLine("ON");
  399.               else DisplayLine("OFF");
  400.               break;
  401.  
  402.             case MSG_BREAK:
  403.               EnableMailMenuItems();
  404.               SetCursor(ArrowCursor);
  405.               wilCancelBlocking();
  406.               wilCloseSocket(Socket);
  407.               break;
  408.  
  409.             case MSG_EXIT:
  410.               wilRelease();
  411.               DestroyWindow(hMainWnd);
  412.               break;
  413.  
  414.             case MSG_MAIL_CHK:
  415.               Pop3Command(MAIL_CHK_BEGIN, POP3_QUIT_FAILURE);
  416.               break;
  417.  
  418.             case MSG_PASS:
  419.               /* set POP3 user password */
  420.               InBufLen = 0;
  421.               InBufCmd = MSG_PASS;
  422.               PassFlag = TRUE;
  423.               DisableMailMenuItems();
  424.               DisplayString("Enter password:");
  425.               SetTheFocus();
  426.               break;
  427.  
  428.             case MSG_MAIL_DEL:
  429.               /* delete mail message on server */
  430.               InBufLen = 0;
  431.               if(lstrlen((LPSTR)Pop3String)==0)
  432.                 {DisplayLine("Missing POP server name.");
  433.                  break;
  434.                 }
  435.               InBufCmd = MSG_MAIL_DEL;
  436.               DisableMailMenuItems();
  437.               DisplayString("Enter message #:");
  438.               SetTheFocus();
  439.               break;
  440.  
  441.             case MSG_MAIL_GET:
  442.               /* get mail */
  443.               InBufLen = 0;
  444.               if(lstrlen((LPSTR)Pop3String)==0)
  445.                 {DisplayLine("Missing POP server name.");
  446.                  break;
  447.                 }
  448.               InBufCmd = MSG_MAIL_GET;
  449.               DisableMailMenuItems();
  450.               DisplayString("Enter message #:");
  451.               SetTheFocus();
  452.               break;
  453.  
  454.             case MSG_MAIL_PUT:
  455.               /* send mail */
  456.               InBufLen = 0;
  457.               if(lstrlen((LPSTR)SmtpString)==0)
  458.                 {DisplayLine("Missing SMTP server name.");
  459.                  break;
  460.                 }
  461.               InBufCmd = MSG_MAIL_PUT;
  462.               DisableMailMenuItems();
  463.               DisplayString("Enter filename:");
  464.               SetTheFocus();
  465.               break;
  466.            }
  467.          break;
  468.  
  469.     case WM_USER: /* posted by WIL */
  470.       AsyncProcessMsg(lParam);
  471.       break;
  472.  
  473.     case WM_USER+1:  /* posted by POST_MSG [defined in async.h] */
  474.       /* test response code */
  475.       if(lParam>=500)
  476.         {/* POP3/SMTP server returns fatal error code */
  477.          POST_MSG(MAIL_CMD_FAILURE);
  478.          break;
  479.         }
  480.       /* execute case */
  481.       switch(wParam)
  482.         {
  483.          case MAIL_CMD_FAILURE:
  484.            DisplayLine("SMTP/POP3 command has failed.");
  485.            EnableMailMenuItems();
  486.            wilCloseSocket(Socket);
  487.            SetCursor(ArrowCursor);
  488.            break;
  489.  
  490.          /* finish up POP3 commands with QUIT command */
  491.  
  492.          case POP3_QUIT_BEGIN:
  493.            AsyncSetEcho(TRUE);
  494.            /* send QUIT command */
  495.            AsyncCommand("QUIT", POP3_QUIT_SUCCESS,
  496.                         POP3_QUIT_FAILURE, ASYNC_PLUS_MINUS);
  497.            break;
  498.  
  499.          case POP3_QUIT_FAILURE:
  500.            DisplayLine("POP3 command has failed...");
  501.            EnableMailMenuItems();
  502.            wilCloseSocket(Socket);
  503.            SetCursor(ArrowCursor);
  504.            break;
  505.  
  506.          case POP3_QUIT_SUCCESS:
  507.            /* all done */
  508.            DisplayLine("POP3 command succeeds.");
  509.            EnableMailMenuItems();
  510.            wilCloseSocket(Socket);
  511.            SetCursor(ArrowCursor);
  512.            break;
  513.  
  514.          /* The POP3_* series of cases connect to the POP3 server, */
  515.          /* then send the USER and PASS commands. On success,      */
  516.          /* the message POP3SuccessMsg is posted, while on failure */
  517.          /* the message POP3Failure is posted. See Pop3Command().  */
  518.  
  519.          case POP3_COMMAND:
  520.            /* log onto POP3 server */
  521.            DisableMailMenuItems();
  522.            SetCursor(WaitCursor);
  523.            AsyncSetEcho(TRUE);
  524.            Socket = AsyncConnect(hMainWnd,"POP3",(LPSTR)Pop3String,
  525.                      POP3_PORT, POP3_CONN_SUCCESS,
  526.                      POP3FailureMsg, ASYNC_PLUS_MINUS);
  527.            break;
  528.  
  529.          case POP3_CONN_SUCCESS:
  530.            /* send USER command */
  531.            wsprintf((LPSTR)Temp,"USER %s", (LPSTR)UserString);
  532.            AsyncCommand((LPSTR)Temp, POP3_USER_SUCCESS,
  533.                         POP3FailureMsg, ASYNC_PLUS_MINUS);
  534.            break;
  535.  
  536.          case POP3_USER_SUCCESS:
  537.            /* send PASS (password) command */
  538.            wsprintf((LPSTR)Temp,"PASS %s", (LPSTR)PassString);
  539.            AsyncCommand((LPSTR)Temp, POP3SuccessMsg,
  540.                         POP3FailureMsg, ASYNC_PLUS_MINUS);
  541.            break;
  542.  
  543.          /***** END - POP3 command cases *****/
  544.  
  545.          case MAIL_CHK_BEGIN:
  546.            /* send STAT (statistics) command */
  547.            AsyncSetEcho(TRUE);
  548.            AsyncCommand("STAT", MAIL_CHK_MSG_COUNT,
  549.                         POP3_QUIT_FAILURE, ASYNC_PLUS_MINUS);
  550.            break;
  551.  
  552.          case MAIL_CHK_MSG_COUNT:
  553.            /* get the message count */
  554.            BufferPtr = AsyncGetBufPtr();
  555.            MsgCount = (int) wilParseDecimal(BufferPtr+4);
  556.            wsprintf((LPSTR)Temp,"  %d messages waiting",MsgCount);
  557.            DisplayLine((LPSTR)Temp);
  558.            /* look at each message in turn */
  559.            MsgIndex = 0;
  560.            POST_MSG(MAIL_CHK_NEXT_HEADER);
  561.            break;
  562.  
  563.          case MAIL_CHK_NEXT_HEADER:
  564.            /* is there another header ? */
  565.            MsgIndex++;
  566.            if(MsgIndex>MsgCount)
  567.              {/* no more headers, so sign off POP server */
  568.               POST_MSG(POP3_QUIT_BEGIN);
  569.               break;
  570.              }
  571.            /* get header for message <MsgIndex> */
  572.            wsprintf((LPSTR)Temp,"TOP %d 0", MsgIndex);
  573.            AsyncCommand((LPSTR)Temp, MAIL_CHK_TOP_SUCCESS,
  574.                         POP3_QUIT_FAILURE, ASYNC_PLUS_MINUS);
  575.            break;
  576.  
  577.          case MAIL_CHK_TOP_SUCCESS:
  578.            /* display header info */
  579.            wsprintf((LPSTR)Temp,"Msg %d: ",MsgIndex);
  580.            DisplayString((LPSTR)Temp);
  581.            /* read 1st line of header info */
  582.            LastChar = '\n';
  583.            AsyncSetEcho(EchoFlag);
  584.            AsyncRead(MAIL_CHK_READ_SUCCESS, POP3_QUIT_FAILURE,
  585.                      ASYNC_SINGLE_LINE);
  586.            break;
  587.  
  588.          case MAIL_CHK_READ_SUCCESS:
  589.            /* read was successfull */
  590.            BufferPtr = AsyncGetBufPtr();
  591.            /* check if this is the last line */
  592.            if((LastChar=='\n')&&(*BufferPtr=='.')&&(*(BufferPtr+1)=='\r') )
  593.              {/* end of this header message */
  594.               DisplayLine("<EOM>");
  595.               POST_MSG(MAIL_CHK_NEXT_HEADER);
  596.               break;
  597.              }
  598.            /* got good header line */
  599.            n = lstrlen((LPSTR)BufferPtr);
  600.            LastChar = *(BufferPtr+n-1);
  601.            /* look for "From" or "Subject" */
  602.            Code = IsLeftString(BufferPtr,(LPSTR)"From");
  603.            if(!Code) Code = IsLeftString(BufferPtr,(LPSTR)"Subject");
  604.            if(Code)
  605.              {StripCRLF(BufferPtr);
  606.               wsprintf((LPSTR)Temp,"%s ",BufferPtr);
  607.               DisplayString((LPSTR)Temp);
  608.              }
  609.            /* read next header line */
  610.            AsyncRead(MAIL_CHK_READ_SUCCESS, POP3_QUIT_FAILURE, ASYNC_SINGLE_LINE);
  611.            break;
  612.  
  613.          case MAIL_DEL_BEGIN:
  614.            AsyncSetEcho(TRUE);
  615.            /* delete message */
  616.            wsprintf((LPSTR)Temp,"DELE %d", MailID);
  617.            AsyncCommand((LPSTR)Temp, POP3_QUIT_BEGIN, POP3_QUIT_FAILURE,
  618.                         ASYNC_PLUS_MINUS);
  619.            break;
  620.  
  621.          case MAIL_GET_BEGIN:
  622.            AsyncSetEcho(TRUE);
  623.            /* send RETR (retrieve) command, & get 1st line of mail */
  624.            wsprintf((LPSTR)Temp,"RETR %d", MailID);
  625.            AsyncCommand((LPSTR)Temp,MAIL_GET_READ, POP3_QUIT_FAILURE,
  626.                         ASYNC_SINGLE_LINE);
  627.            LastChar = '\n';
  628.            break;
  629.  
  630.          case MAIL_GET_READ:
  631.            /* got line of text */
  632.            BufferPtr = AsyncGetBufPtr();
  633.            BufSize = lstrlen((LPSTR)BufferPtr);
  634.            /* is there a '.' in CC1 ? */
  635. #if 0
  636. wsprintf((LPSTR)Temp,"<%c>",*BufferPtr);/*DEL*/
  637. DisplayLine((LPSTR)Temp);/*DEL*/
  638. #endif
  639.            if((LastChar=='\n')&&(*BufferPtr=='.')&&(*(BufferPtr+1)=='\r') )
  640.              {/* close file */
  641.               DisplayLine("<EOM>");
  642.               wsprintf((LPSTR)Temp,"Message %d to file %s",
  643.                          MailID,(LPSTR)MailFile);
  644.               DisplayLine((LPSTR)Temp);
  645.               _lclose(Handle);
  646.               DisplayLine("");
  647.               POST_MSG(POP3_QUIT_BEGIN);
  648.               break;
  649.              }
  650.            /* record last char of line */
  651.            if(BufSize) LastChar = BufferPtr[BufSize-1];
  652.            else LastChar = '\n'; /*???*/
  653.            /* write to disk */
  654.            Code = _lwrite(Handle,(LPSTR)BufferPtr,BufSize);
  655.            if(Code<0)
  656.              {DisplayLine("Error writting disk");
  657.               _lclose(Handle);
  658.               POST_MSG(POP3_QUIT_FAILURE);
  659.               break;
  660.              }
  661.            /* wait for next line */
  662.            AsyncRead(MAIL_GET_READ, POP3_QUIT_FAILURE, ASYNC_SINGLE_LINE);
  663.            break;
  664.  
  665.          case MAIL_PUT_BEGIN:
  666.            AsyncSetEcho(TRUE);
  667.            /* send mail using SMTP */
  668.            DisableMailMenuItems();
  669.            SetCursor(WaitCursor);
  670.            Socket = AsyncConnect(hMainWnd,"SMTP",(LPSTR)SmtpString,
  671.                      SMTP_PORT, MAIL_PUT_CONN_SUCCESS,
  672.                      SMTP_QUIT_FAILURE, ASYNC_SINGLE_LINE);
  673.            break;
  674.  
  675.          case MAIL_PUT_CONN_SUCCESS:
  676.            /* send HELO (hello) command */
  677.            Ptr = StringChar((LPSTR)FromString,'@');
  678.            wsprintf((LPSTR)Temp,"HELO %s",(LPSTR)(Ptr+1));
  679.            AsyncCommand((LPSTR)Temp, MAIL_PUT_HELO_SUCCESS,
  680.                        SMTP_QUIT_FAILURE, ASYNC_SINGLE_CODED);
  681.            break;
  682.  
  683.          case MAIL_PUT_HELO_SUCCESS:
  684.            /* send MAIL FROM command */
  685.            wsprintf((LPSTR)Temp,"MAIL FROM:<%s>",(LPSTR)FromString);
  686.            AsyncCommand((LPSTR)Temp,MAIL_PUT_FROM_SUCCESS,
  687.                        SMTP_QUIT_FAILURE, ASYNC_SINGLE_CODED);
  688.            break;
  689.  
  690.          case MAIL_PUT_FROM_SUCCESS:
  691.            /* send RCPT TO (receipt to) command */
  692.            wsprintf((LPSTR)Temp,"RCPT TO:<%s>",(LPSTR)ToString);
  693.            AsyncCommand((LPSTR)Temp, MAIL_PUT_TO_SUCCESS,
  694.                        SMTP_QUIT_FAILURE, ASYNC_SINGLE_CODED);
  695.            break;
  696.  
  697.          case MAIL_PUT_TO_SUCCESS:
  698.            /* send DATA command */
  699.            AsyncCommand("DATA", MAIL_PUT_DATA_SUCCESS,
  700.                         SMTP_QUIT_FAILURE, ASYNC_SINGLE_CODED);
  701.            break;
  702.  
  703.          case MAIL_PUT_DATA_SUCCESS:
  704.            AsyncSetEcho(EchoFlag);
  705.            /* get next line from disk */
  706.            BufSize = ReadTextLine(Handle, (LPSTR)InBuffer, MAX_BUF);
  707.            if(BufSize<=0)
  708.              {/* end of file */
  709.               _lclose(Handle);
  710.               /* append line with only '.' */
  711.               wilWriteString(Socket,".\r\n");
  712.               DisplayLine("<EOF>");
  713.               POST_MSG(SMTP_QUIT_BEGIN);
  714.               break;
  715.              }
  716.            /* ready to send text line */
  717.            POST_MSG(MAIL_PUT_SEND);
  718.            break;
  719.  
  720.          case MAIL_PUT_SEND:
  721.            /* does buffer consist of lone '.' ? */
  722.            if((InBuffer[0]=='.')&&(InBuffer[1]=='\r')&&(InBuffer[2]=='\n'))
  723.              {/* "quote" the period */
  724.               InBuffer[1] = '.';
  725.               InBuffer[2] = '\r';
  726.               InBuffer[3] = '\n';
  727.               InBuffer[4] = '\0';
  728.               BufSize = 4;
  729.              }
  730. #if 0
  731.            /* display # bytes being sent */
  732.            wsprintf((LPSTR)Temp,"Sending %d bytes.", BufSize);
  733.            DisplayLine((LPSTR)Temp);
  734. #endif
  735.            /* send the buffer */
  736.            Code = wilWriteSocket(Socket,(LPSTR)InBuffer,BufSize);
  737.            if(Code<0)
  738.              {/* socket write error */
  739.               DisplayError(Code, "WriteSocket:");
  740.               POST_MSG(SMTP_QUIT_FAILURE);
  741.               break;
  742.              }
  743.            if(EchoFlag) WriteTheString((LPSTR)InBuffer,BufSize);
  744.            /* go get another buffer to write */
  745.            BufSize = 0;
  746.            POST_MSG(MAIL_PUT_DATA_SUCCESS);
  747.            break;
  748.  
  749.          case SMTP_QUIT_BEGIN:
  750.            AsyncSetEcho(TRUE);
  751.            /* send QUIT command */
  752.            AsyncCommand("QUIT", SMTP_QUIT_SUCCESS,
  753.                         SMTP_QUIT_FAILURE, ASYNC_SINGLE_CODED);
  754.            break;
  755.  
  756.          case SMTP_QUIT_FAILURE:
  757.            DisplayLine("SMTP command has failed...");
  758.            EnableMailMenuItems();
  759.            wilCloseSocket(Socket);
  760.            SetCursor(ArrowCursor);
  761.            break;
  762.            /* fall thru... */
  763.  
  764.          case SMTP_QUIT_SUCCESS:
  765.            /* all done */
  766.            DisplayLine("SMTP command succeeds.");
  767.            EnableMailMenuItems();
  768.            wilCloseSocket(Socket);
  769.            SetCursor(ArrowCursor);
  770.            break;
  771.         } /* end-switch(wParam) */
  772.  
  773.     case WM_PAINT:
  774.       HideCaret(hMainWnd);
  775.       hDC = BeginPaint(hMainWnd, &ps);
  776.       SetMapMode(hDC,MM_ANISOTROPIC);
  777.       SelectObject(hDC, GetStockObject(OEM_FIXED_FONT) );
  778.       PaintMain(hDC,&ps);
  779.       EndPaint(hMainWnd,&ps);
  780.       SetCaretPos(PaintGetColPos(),PaintGetRowPos());
  781.       ShowCaret(hMainWnd);
  782.       break;
  783.  
  784.     case WM_DESTROY:
  785.       PostQuitMessage(0);
  786.       break;
  787.  
  788.     case WM_CHAR:
  789.       /* user just typed character */
  790.       if(wParam==CR)
  791.         {/* user has completed input */
  792.          DestroyCaret();
  793.          EnableMailMenuItems();
  794.          PassFlag = FALSE;
  795.          DisplayChar(LF);
  796.          InBuffer[InBufLen] = '\0';
  797.          /* excute command */
  798.          switch(InBufCmd)
  799.             {case MSG_PASS:
  800.                InBufCmd = 0;
  801.                /* save password string */
  802.                lstrcpy((LPSTR)PassString,(LPSTR)InBuffer);
  803.                break;
  804.  
  805.              case MSG_MAIL_DEL:
  806.                InBufCmd = 0;
  807.                /* get message number to delete */
  808.                MailID = (int) wilParseDecimal((LPSTR)InBuffer);
  809.                wsprintf((LPSTR)Temp,"Deleting message %d",MailID);
  810.                Pop3Command(MAIL_DEL_BEGIN, POP3_QUIT_FAILURE);
  811.                break;
  812.  
  813.              case MSG_MAIL_GET:
  814.                InBufCmd = 0;
  815.                MailID = (int) wilParseDecimal((LPSTR)InBuffer);
  816.                /* contruct unique mail file name (starting with date) */
  817.                unique((LPSTR)MailFile);
  818.                wsprintf((LPSTR)Temp,"Saving message %d to file %s",
  819.                          MailID,(LPSTR)MailFile);
  820.                DisplayLine((LPSTR)Temp);
  821.                /* create mail file */
  822.                Handle = _lcreat((LPSTR)MailFile,0);
  823.                if(Handle<0)
  824.                  {DisplayString("Cannot create ");
  825.                   DisplayLine((LPSTR)MailFile);
  826.                   break;
  827.                  }
  828.                /* start up mail receive */
  829.                wsprintf((LPSTR)Temp,"File %s is created",(LPSTR)MailFile);
  830.                DisplayLine((LPSTR)Temp);
  831.                Pop3Command(MAIL_GET_BEGIN, POP3_QUIT_FAILURE);
  832.                break;
  833.  
  834.              case MSG_MAIL_PUT:
  835.                InBufCmd = 0;
  836.                /* open mail file */
  837.                lstrcpy((LPSTR)MailFile, (LPSTR)InBuffer);
  838.                Handle = _lopen((LPSTR)MailFile,OF_READ|OF_SHARE_DENY_WRITE);
  839.                if(Handle<0)
  840.                  {DisplayString("Cannot open ");
  841.                   DisplayLine((LPSTR)MailFile);
  842.                   break;
  843.                  }
  844.                wsprintf((LPSTR)Temp,"File %s opened",(LPSTR)MailFile);
  845.                DisplayLine((LPSTR)Temp);
  846.                /* read email address from 1st line of mail file */
  847.                *ToString = '\0';
  848.                for(i=0;i<STR_SIZE; )
  849.                  {n = _lread(Handle,(LPSTR)&Chr,1);
  850.                   if(n<=0) break;
  851.                   if(Chr=='\n')
  852.                      {ToString[i] = '\0';
  853.                       break;
  854.                      }
  855.                   if(Chr=='\r') ;
  856.                   else ToString[i++] = Chr;
  857.                  }
  858.                /* display IP address */
  859.                wsprintf((LPSTR)Temp,"Address ='%s'", (LPSTR)ToString);
  860.                DisplayLine(Temp);
  861.                /* send mail [SMTP] */
  862.                Ptr = StringChar((LPSTR)FromString,'@');
  863.                if(Ptr==NULL)
  864.                  {wsprintf((LPSTR)Temp,"Missing address in %s",(LPSTR)FromString);
  865.                   DisplayLine((LPSTR)Temp);
  866.                   break;
  867.                  }
  868.                POST_MSG(MAIL_PUT_BEGIN);
  869.                break;
  870.  
  871.              default:
  872.                break;
  873.             }
  874.         }
  875.       else
  876.         {/* add char to input buffer */
  877.          Add2Buffer((char) wParam);
  878.         }
  879.       break;
  880.  
  881.     default:
  882.       return (DefWindowProc(hMainWnd, iMsg, wParam, lParam));
  883.    }
  884.  return 0;
  885. } /* end MainWndProc */                                                                                                                              
  886.